Python学习笔记(六)函数的参数

1.位置参数

调用函数时,传入的值按照参数的位置顺序依次赋给参数。

2.默认参数

默认参数很有用,但是使用不当可能掉坑里,默认参数有个最大的坑,如下:

def add_end(L=[]):
L.append('End')
return L
使用默认参数时,结果是正确的:
>>>add_end()
['End']
但是,再次调用时,结果就不对了:
>>>add_end()
['End', 'End']
>>>add_end()
['End', 'End', 'End']
原因:Python函数在定义时,默认参数L的值就被计算出来了,即[],因为L也是一个变量,它指向对象[],每次调用该函数,如果改变了[]的内容,则下次调用时,默认参数的内容就变了,不再是[]了。
解决方案:使用None这个不变对象来实现

def add_end(L=None):
    if L is None:
        L = []
    L.append('END')
    return L
无论怎么调用都不会出错:
>>>add_end()
['End']
>>>add_end()
['End']

为什么要设计str、None这样的不变对象呢。不变对象一旦创建,对象内部的数据就不能修改,这样就减少了因为修改数据导致的错误,此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。编写程序时,如果能设计一个不变对象,尽量设计成不变对象。

3.可变参数

即传入的参数个数是可变的。以一个数学题为例,给定一组数字a,b,c...,计算a2+b2+c2+...
要定义出这个函数,我们必须确定输入的参数,由于参数个数不确定,可以想到把a,b,c作为一个list或tuple传进来,如下:

def calc(numbers):
    sum = 0
    for n in numbers:
        sum = sum + n*n
    return sum
>>>calc([1,2,3])
14
>>>calc([])
0

利用可变参数,可变为如下:

def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n*n
    return sum
>>>calc(1,2,3)
14
>>>calc()
0

如有一已知的list或tuple,调用时前面加*号:

list1 = [1,2,3]
>>>calc(*list1)
14

4.关键字参数

关键字参数允许传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。
函数person除了必选参数nameage外,还接受关键字参数kw,在调用函数时,可以只传入必选参数,也可以传入任意个的关键字参数:

test.py:
def person(name, age, **kw):
    print('name:', name, 'age:', age, 'other:', kw)

extra = {'city': 'Beijing', 'job': 'Engineer'}
person('Tom', 40)
person('Jack', 25, city='Beijing', job = 'Engineer')
person('Jack', 25, **extra)

iTerm终端:
>>>python3 ~/python_test/test.py
name: Tom age: 40 other: {}
name: Jack age: 25 other: {'city': 'Beijing', 'job': 'Engineer'}
name: Jack age: 25 other: {'city': 'Beijing', 'job': 'Engineer'}
注意:kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外地extra。

关键字参数可以扩展函数功能,比如用在用户注册信息时,有些信息是必填项,有些信息是选填项。

5.命名关键字参数

对于关键字参数,函数调用者可以传入任意不受限制的关键字参数,至于到底传入了哪些,需要在函数内部进行检查:

test.py:
def person(name, age, **kw):
    if 'city' in kw:
        print("there is a 'city' key")
    if 'job' in kw:
        print("there is a 'job' key")
    print('name:', name, 'age:', age, 'other:', kw)

extra = {'city': 'Beijing', 'job': 'Engineer'}
person('Tom', 40)
person('Jack', 25, **extra)

iTerm终端:
>>>python3 ~/python_test/test.py
name: Tom age: 40 other: {}
there is a 'city' key
there is a 'job' key
name: Jack age: 25 other: {'city': 'Beijing', 'job': 'Engineer'}

但是调用者仍然可以传入不受限制的关键字参数,如果要限制关键字参数的名字,就可以使用命名关键字参数,例如,只接收cityjob作为关键字参数,则定义如下:

def person(name, age, *, city, job):
    print(name, age, city, job)

和关键字参数**kw不同,命名关键字参数需要一个特殊的分隔符**后面的参数视为命名关键字参数,其调用如下:

>>>person('Jack', 25, city='Beijing', job = 'Engineer')
Jack 25 Beijing Engineer

如果函数定义中已经有一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊的分隔符*了:

# ~/python_test/test.py
def person(name, age, \*args, city, job):
    print(name, age, args, city, job)
person('Jack', 24, 'Beijing', 'Engineer')

命名关键字参数必须传入参数名,这和位置参数不同,如果没有传入参数名,系统将报错:

>>>python3 ~/python_test/test.py
Traceback (most recent call last):
  File "/Users/lijing/python_test/test.py", line 4, in <module>
    person('Jack', 25, 'Beijing', 'Engineer')
TypeError: person() missing 2 required keyword-only arguments: 'city' and 'job'

由于调用时缺少参数名cityjob,python解释器把四个参数都视为了位置参数,但是person函数只接受nameage两个位置参数,因此报错。此外命名关键字参数还可以使用默认缺省值:

def person(name, age, *, city = 'Beijing', job):
    print(name, age, city, job)

调用时可以不传入city参数,使用默认值'Beijing'
注意:使用命名关键字时,要特别注意*的使用,没有可变参数时必须加一个*作为特殊分隔符,如果缺少*,python解释器将无法识别位置参数和命名关键字参数。

6.参数组合

在python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用,但注意参数定义顺序必须是必选参数、默认参数、可变参数、命名关键字参数、关键字参数:
函数在调用时,python解释器自动按照参数位置和参数名把对应的参数传进去,而且,通过一个tuple和dict,也可以调用该函数:

# ~/python_test/test.py
def f1(a, b, c=0, *args, **kw):
    print(a, b, c, args, kw)
def f2(a, b, c=0, *, d, **kw):
    print(a, b, c, d, kw)
args = {1, 2, 3}
kw = {'d':99, 'x':'#'}

f1(1,2)
f1(1,2,c=3)
f1(1,2,3,'a','b')
f1(1,2,3,'a','b',x=99)
f2(1,2,d=99,ext=None)
f1(*args, **kw)
f2(*args, **kw)

#iTerm2终端:
>>>python3 ~/python_test/test.py
1 2 0 () {}
1 2 3 () {}
1 2 3 ('a', 'b') {}
1 2 3 ('a', 'b') {'x': 99}
1 2 0 99 {'ext': None}
1 2 3 () {'d': 99, 'x': '#'}
1 2 3 99 {'x': '#'}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容